/*!
\file Graph.h
\brief Contains declaration of Graph.
\ingroup Graph
*/

#ifndef GRAPH_H
#define GRAPH_H

#include"Node.h"
#include"Edge.h"
#include"EdgeList.h"

class Action;

#include<QList>
#include<QString>
#include<QStringList>
#include<QObject>

/*!
\defgroup Graph Graph Module
This module contains all Graph-related classes.
*/

/*!
\class Graph
\brief Represents a Graph that can be queried and manipulated in an Algorithm.
\ingroup Graph
*/

class Graph: public QObject{
Q_OBJECT
public:
	Graph( bool directed = false );
	//!< Constructor. Needs to know wether or not this will be a directed Graph.
	~Graph();
	//!< Destructor.
	
	//Load a graph from a file.
	static Graph *fromFile( const char *file );
	//!< Returns a Graph loaded from file with given name.
	
	//Node and Edge constructors. Will immediately add edge/node to Graph.
	Node createNode( int id = -1 );
	//!< Create a Node. \param id must be unique and positive, otherwise the Graph will assign one itself. Immediately added to Graph.
	Node createNode( QString label, int id = -1 );
	//!< Create a Node. \param id must be unique and positive, otherwise the Graph will assign one itself. Immediately added to Graph. \param label contains this Node's label.
	Edge createEdge( Node from, Node to, QString label = QString(), int identifier = -1 );
	//!< Create an Edge. identifier must be unique and positive, otherwise the Graph will assign one itself. Immediately added to Graph.
	
	//Add edge/node to Graph. Since edge/node constructors are private, can only be used if edge/node was previously removed.
	bool addEdge( Edge edge );
	//!< Add Edge to Graph. Since Edge constructors are private, can only be used if Edge was previously removed and stored by user.
	bool addNode( Node node );
	//!< Add Node to Graph. Since Node constructors are private, can only be used if Node was previously removed and stored by user.
	
	//Remove an edge or node
	void removeEdge( const Edge &edge );
	//!< Remove an Edge from this Graph.
	void removeNode( const Node &node );
	//!< Remove a Node from this Graph.
	
	//Query if a certain edge/node still is in the graph.
	bool hasEdge( const Edge &edge )const;
	//!< Returns wether or not an Edge is in this Graph.
	bool hasNode( const Node &node )const;
	//!< Returns wether or not a Node is in this Graph.
	
	//Query for the amount of nodes/edges.
	unsigned int numNodes()const{ return m_nodes.size(); }
	//!< Returns amount of Nodes.
	unsigned int numEdges()const{ return m_edges.size(); }
	//!< Returns amount of Edges.
	
	//Return i-th edge/node. i should NOT be confused with an element's identifier.
	Node node( int i )const;
	//!< Returns i'th Node. i should not be confused with a Node's identifier.
	Edge edge( int i )const;
	//!< Returns i'th Edge. i should not be confused with an Edge's identifier.
	
	//Return edge/node with identifier i. If not found, first element will be returned and *ok be set to false.
	Node nodeWithId(int i, bool *ok = 0)const;
	//!< Returns Node with identifier i. It not found, first element will be returned and *ok be set to false.
	Edge edgeWithId(int i, bool *ok = 0)const;
	//!< Returns Edge with identifier i. It not found, first element will be returned and *ok be set to false.
	
	//Query wether or not graph is directed.
	bool isDirected()const{ return m_isDirected; }
	//!< Returns wether or not this Graph is directed.
	
	//Returns all neighbours of node. This means, all nodes for which at least one edge connects them directly with given node.
	QList<Node> neighboursOf( const Node &node );
	//!< Returns all neighbours of Node. This means, all Nodes for which at least one Edge connects them directly with given Node.
	//Returns all nodes reachable from node. If graph is directed, edge must be FROM node TO the node in the return list.
	QList<Node> reachableFrom( const Node &node );
	//!< Returns all nodes reachable from Node. If Graph is directed, Edge must be FROM this Node TO the Node in the return list. If not directed, this is equal to neighboursOf().
	//Returns all edges starting from given node. If graph undirected, this includes edges that end in given node.
	QList<Edge> edgesFrom( const Node &node );
	//!< Returns all Edges starting from given Node. If Graph undirected, this includes edges that end in given Node.
	
	//Calling [i][j] operator returns the ID of the edge from node with ID i to node with ID j. -1 if not found. If more such edges exists, returns ID of the first that is found.
	EdgeList operator[](int i)const;
	//!< Calling [i][j] operator returns the ID of the Edge from node with ID i to Node with ID j. -1 if not found. If more such Edges exist, returns the ID of the first Edge that is found.
	
	//Should not be called by user. TODO
	QStringList toDOT()const;
	//!< Returns DOT representation of Graph. Should not be called by user.
	
	void report( Action *action )const;
	//!< Report an Action. Should not be called by user.
private:
	QList<Node> m_nodes;//!< Contains all the Graph's Nodes.
	QList<Edge> m_edges;//!< Contains all the Graph's Edges.
	bool m_isDirected;
	
	void _nodesToDOT( QStringList &result )const;
	void _edgesToDOT( QStringList &result )const;
	
	QList<int> m_edgeIdentifiers;
	QList<int> m_nodeIdentifiers;
	
	int _getNewEdgeIdentifier();
	bool _registerEdgeIdentifier( int identifier );
	int _getNewNodeIdentifier();
	bool _registerNodeIdentifier( int identifier );
signals:
	void reportAction( Action *action )const;
	//!< Reports an Action to Algorithm parent.
protected:
	void _fromFile( const char *file );
	//!< Load Graph from file. This is called by the similar static function.
};

#endif

